package niconama04.parser.impl;

import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Stack;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import niconama04.parser.ParseResult;
import niconama04.parser.Parser;
import niconama04.shared.data.Constants.Pos;
import niconama04.shared.data.Original;
import niconama04.shared.data.Word;
import niconama04.utility.PropertyUtility;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

/**
 * <p>
 * パーサ実装クラス
 * </p>
 * <p>
 * Yahoo 形態素解析を利用している
 * </p>
 * 
 * @author brigen
 */
class YahooWebApiParser implements Parser {

	/** URL */
	private static final String YAHOO_URL = "http://jlp.yahooapis.jp/MAService/V1/parse?appid=";

	/** APPLICATION ID */
	private static final String YAHOO_APPLICATION_ID = PropertyUtility.getInstance().getAsString("yahoo.develop.api.key");

	/** URL PARAMETERS */
	private static final String YAHOO_URL_PARAMS = "&results=ma&response=surface,reading,pos,baseform&sentence=";

	/**
	 * 解析する
	 *
	 * @param x_value 文字列
	 * @return 解析結果
	 */
	@Override
	public ParseResult parse(String x_value) throws Exception {
		SAXParserFactory spfactory = SAXParserFactory.newInstance();
		SAXParser parser = spfactory.newSAXParser();
		HttpURLConnection urlconn = null;
		YahooHandler handler = new YahooHandler();
		try {
			urlconn = (HttpURLConnection) buildURL(x_value).openConnection();
			urlconn.setRequestMethod("GET");
			urlconn.setInstanceFollowRedirects(false);
			urlconn.setRequestProperty("Accept-Language", "ja;q=0.7,en;q=0.3");
			urlconn.connect();
			parser.parse(urlconn.getInputStream(), handler);
		} finally {
			if (urlconn != null) {
				urlconn.disconnect();
			}
		}
		return handler.getResult();
	}

	private URL buildURL(String x_value) throws MalformedURLException, UnsupportedEncodingException {
		return new URL(YAHOO_URL + YAHOO_APPLICATION_ID + YAHOO_URL_PARAMS + URLEncoder.encode(x_value, "UTF-8"));
	}

	/**
	 * <p>
	 * SAXハンドラクラス
	 * </p>
	 * <p>
	 * ※スレッドセーフではない
	 * </p>
	 * 
	 * @author brigen
	 */
	class YahooHandler extends DefaultHandler {

		/** 解析結果 */
		private ParseResult parseResult;

		/** パス */
		private String path;

		/** タグスタック */
		private Stack<String> tagStack;

		/** 解析フラグ */
		private boolean parseFlg;

		/** 単語 */
		private Word word;

		/** バッファ */
		private StringBuilder buffer;

		@Override
		public void startDocument() {
			parseResult = new ParseResult();
			parseResult.setWords(new ArrayList<Word>());
			path = "";
			tagStack = new Stack<String>();
			buffer = new StringBuilder();
		}

		@Override
		public void startElement(String x_uri, String x_localName, String x_qName, Attributes x_attributes) {
			{
				tagStack.push(x_qName);
				path += ("/" + x_qName);
			}
			if (x_qName.equals("ma_result")) {
				parseFlg = true;
			} else if (parseFlg && x_qName.equals("word")) {
				word = new Word();
				word.setOriginal(new Original());
				parseResult.getWords().add(word);
			}
		}

		@Override
		public void characters(char[] ch, int offset, int length) {
			if (!parseFlg) {
				return;
			}
			buffer.append(new String(ch, offset, length));
		}

		@Override
		public void endElement(String x_uri, String x_localName, String x_qName) {
			String tag = x_qName;
			{
				tagStack.pop();
				path = path.substring(0, path.lastIndexOf("/"));
			}
			if (!parseFlg) {
				return;
			}
			String value = buffer.toString();
			buffer.setLength(0);
			if (tag.equals("ma_result")) {
				parseFlg = false;
			} else if (tag.equals("total_count")) {
				parseResult.setTotalCount(Integer.parseInt(value));
			} else if (tag.equals("filtered_count")) {
				parseResult.setFilteredCount(Integer.parseInt(value));
			} else if (tag.equals("word")) {
				if (word.getPos() == null) {
						word.setPos(Pos.HUMEI);
				}
				word.setPosKey(word.getPos().getKey());
				word.getOriginal().setPosKey(word.getPos().getKey());
				if (word.getBaseform() == null) {
					word.setBaseform(word.getSurface());
				}
			} else if (tag.equals("surface")) {
				word.setSurface(value);
			} else if (tag.equals("reading")) {
				word.setReading(value);
			} else if (tag.equals("pos")) {
				if (value.equals("形容詞")) {
					word.setPos(Pos.KEIYOUSHI);
				} else if (value.equals("形容動詞")) {
					word.setPos(Pos.KEIYOUDOUSHI);
				} else if (value.equals("感動詞")) {
					word.setPos(Pos.KANDOUSHI);
				} else if (value.equals("副詞")) {
					word.setPos(Pos.HUKUSHI);
				} else if (value.equals("連体詞")) {
					word.setPos(Pos.RENTAISHI);
				} else if (value.equals("接続詞")) {
					word.setPos(Pos.SETSUZOKUSHI);
				} else if (value.equals("接頭辞")) {
					word.setPos(Pos.SETTOUJI);
				} else if (value.equals("接尾辞")) {
					word.setPos(Pos.SETSUBIJI);
				} else if (value.equals("名詞")) {
					word.setPos(Pos.MEISHI);
				} else if (value.equals("動詞")) {
					word.setPos(Pos.DOUSHI);
				} else if (value.equals("助詞")) {
					word.setPos(Pos.JOSHI);
				} else if (value.equals("助動詞")) {
					word.setPos(Pos.JODOUSHI);
				} else if (value.equals("特殊")) {
					word.setPos(Pos.TOKUSHU);
				}
				word.getOriginal().setPos(word.getPos());
			} else if (tag.equals("baseform")) {
				word.setBaseform(value);
				word.getOriginal().setBaseform(value);
			}
		}

		/**
		 * 解析結果を返す
		 *
		 * @return 解析結果
		 */
		ParseResult getResult() {
			return parseResult;
		}
	}
}
